#include "Shader.hpp"

#include "Debug.hpp"

#include <fstream>


Shader::Shader()
  : m_handle(0), m_type(0),  m_filename(), m_log(0)
{
}

Shader::~Shader()
{
  if (m_handle) {
    glDeleteShader(m_handle);
  }
  
  if (m_log) {
    delete [] m_log;
  }
  
}

void Shader::load(GLenum type, const std::string & filename)
{
  m_filename = filename;
  std::ifstream file(filename.c_str());
  if (!file) {
    ERROR("Could not open file: %s", filename.c_str());
    return;
  }
  
  // c++ seems a bit funny the added parenthasis is required - no idea why
  std::string source( (std::istreambuf_iterator<char>(file)) ,
                      (std::istreambuf_iterator<char>()    ) );
  
  file.close();
  
  if (m_handle) {
    glDeleteShader(m_handle);
  }
  
  m_handle = glCreateShader(type);
  if (!m_handle) {
    ERROR("glCreateShader() returned zero");
    return;
  }
  
  const char * line = source.c_str();
  glShaderSource(m_handle, 1, &line, NULL);
  
}

void Shader::compile()
{
  
  if (!m_handle) {
    ERROR("Invalid shader state");
  }
  
  glCompileShader(m_handle);
  
  GLint compileStatus;
  glGetShaderiv(m_handle, GL_COMPILE_STATUS, &compileStatus);
  
  // sometimes there are compilation warnings about deprecated features
  GLint infoLogLength;
  glGetShaderiv(m_handle, GL_INFO_LOG_LENGTH, &infoLogLength);
    
  m_log = new GLchar[infoLogLength];
  glGetShaderInfoLog(m_handle, infoLogLength, NULL, m_log);
  
  
  if (compileStatus != GL_TRUE) {
    ERROR("Compilation of '%s' failed\n"
          "Compilation Log:\n%s\n",
          m_filename.c_str(), m_log);
    return;
  }
  
  if (m_log[0] != '\0') {
    DEBUG("Compilation Log:\nFile: %s\n%s\n", m_filename.c_str(), m_log);
  }
  
}

void Shader::postDelete()
{
  if (m_handle) {
    glDeleteShader(m_handle);
    m_handle = 0;
  }
  
  if (m_log) {
    delete [] m_log;
    m_log = 0;
  }
  
}
